/*
 * Copyright 2011 yura.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.opu.db_vdumper.util.datacopy;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import org.opu.db_vdumper.util.Logger;

/**
 *
 * @author yura
 */
public class FileDatabase extends Database {
    private BufferedWriter out;
    private Buffer buffer;
    String lineSeparator = System.getProperty("line.separator");
//            (String) java.security.AccessController.doPrivileged(
//               new sun.security.action.GetPropertyAction("line.separator"));

    public FileDatabase(File file) throws IOException{
        this(new BufferedWriter(new FileWriter(file)));
    }
    
    public FileDatabase(BufferedWriter out) {
        this.out = out;
        this.buffer = new Buffer();
    }
    
    @Override
    public void connect(String driver, String url, String user, String pswd)
    		throws DatabaseException {
    	throw new DatabaseException("Can't open connection in file database");
    }

    @Override
    public DbResponse execute(String sql) throws DatabaseException {
        try {
            buffer.append(sql).append(";").appendNewLine();
            return new DbResponse(true, null);
        } catch (IOException ex) {
            throw new DatabaseException(ex);
        }
    }

    @Override
    public MiniPreparedStatement prepareStatement(final String sql) 
            throws DatabaseException {

        return new MiniPreparedStatementImpl(sql);
    }

    @Override
    public boolean tableExists(String t, String s) throws DatabaseException {
        return true;
    }

    @Override
    public void close() throws DatabaseException {
        try {
            buffer.flush();
            out.close();
        } catch (IOException ex) {
            throw new DatabaseException(ex);
        }
    }

    class MiniPreparedStatementImpl implements MiniPreparedStatement {

        private final String sql;
        private Map<Integer, String> data = new HashMap<Integer, String>();

        public MiniPreparedStatementImpl(String sql) {
            this.sql = sql;
        }

        @Override
        public void setString(int i, String string) throws SQLException {
            data.put(new Integer(i), string);
        }

        @Override
        public void setObject(int i, Object object) throws SQLException {
            data.put(new Integer(i), String.valueOf(object));
        }

        @Override
        public void execute() throws SQLException {
            Object[] arr = new Object[data.size()];

            for (Integer index : data.keySet()) {
                arr[index - 1] = String.valueOf(data.get(index));
            }

            try {
                buffer.append(DataMoverUtility.createQuery(sql, arr))
                        .append(";").appendNewLine();
            } catch (IOException ex) {
                throw new SQLException(ex);
            }
        }

        @Override
        public void close() throws SQLException {
            try {
                buffer.appendNewLine();
                buffer.flush();
            } catch (IOException ex) {
                throw new SQLException(ex);
            }
        }
    }


    class Buffer {
        /** Number of character in five megabyte */
        public static final int FIVE_MEGABYTE = 2621440;

        private StringBuffer buffer = new StringBuffer();

        public Buffer append(String str) throws IOException {
            buffer.append(str);

            if (buffer.length() >= FIVE_MEGABYTE){
                flush();
            }

            return this;
        }

        public Buffer appendNewLine() throws IOException {
            return append(lineSeparator);
        }

        public void flush() throws IOException{
            String toString = buffer.toString();
            out.write(toString);
//            System.out.println(toString);
//            out.flush();
            buffer = new StringBuffer();
        }
    }

//    @Override
//    protected void finalize() throws Throwable {
//        try {
//            close();
//        } catch (Exception ex) {
//            Logger.getInstance().fatal(this, ex);
//        }
//    }
}
